package main

import (
	"errors"
	"fmt"
	"net"
	"os"
)

func main() {
	//netError()
	fmt.Println("\n-------")

	//noSuchFileError()
	fmt.Println("\n-------")

	//newError()
	fmt.Println("\n-------")

	//printError()
	fmt.Println("\n-------")

	//i, err := testDiyError(1)
	//if err != nil {
	//	fmt.Println(err)
	//	myerr, ok := err.(*MyDiyError)
	//	if ok {
	//		fmt.Println(myerr.msg)
	//		fmt.Println(myerr.code)
	//	}
	//}
	//fmt.Println(i)
	fmt.Println("\n-------")

	/*
		step1: 触发panic
		step2：逆序执行testPanic函数中的panic前的3条defer语句
		step3：执行到第三条defer时，recover恢复恐慌并输出信息
		step4：返回外部函数，程序继续执行
		由于recover恢复恐慌，所以程序就不会因为panic而退出执行，外部函数还能够正常执行下去
	*/
	defer fmt.Println("main----1")
	defer fmt.Println("main----2")
	fmt.Println("main---3")
	testPanic(1)
	fmt.Println("main---4")
	defer fmt.Println("main----5")
}

func testPanic(num int) {
	defer func() {
		msg := recover()
		if msg != nil {
			fmt.Println("msg:", msg, "--程序恢复了执行")
		}
	}()

	defer fmt.Println("test----1")
	defer fmt.Println("test----2")
	fmt.Println("test----3")
	if num == 1 {
		panic("出现异常----panic")
	}
	fmt.Println("test----4")
	defer fmt.Println("test----5")
}

func testDiyError(i int) (int, error) {
	if i != 0 {
		return i, &MyDiyError{"非零数据", 500}
	}
	return i, nil
}

type MyDiyError struct {
	msg  string
	code int
}

// 实现Error接口
func (e MyDiyError) Error() string {
	return fmt.Sprint("错误信息：", e.msg, "状态码：", e.code)
}

func netError() {
	addrs, err := net.LookupHost("www.baidu111111111.com")
	fmt.Println(err)

	dnsError, ok := err.(*net.DNSError)
	if ok {
		if dnsError.Timeout() {
			fmt.Println("超时")
		} else if dnsError.Temporary() {
			fmt.Println("临时错误")
		} else {
			fmt.Println("其他错误")
		}
	}
	fmt.Println(addrs)
}

func printError() {
	errorinfo2 := fmt.Errorf("我是一个错误：%d", 500)
	fmt.Println(errorinfo2)
	fmt.Printf("%T\n", errorinfo2)
}

func newError() {
	errorinfo := errors.New("我是一个错误信息")
	fmt.Println(errorinfo)
	fmt.Printf("%T\n", errorinfo)

	err := setAge(-1)
	if err != nil {
		fmt.Println(err)
	}
}

func noSuchFileError() {
	file, err1 := os.Open("aaa.txt")
	if err1 != nil {
		fmt.Println(err1)
		temp, ok := err1.(*os.PathError)
		if ok {
			fmt.Println(temp.Op)
			fmt.Println(temp.Err)
			fmt.Println(temp.Path)
		}
		return
	}
	fmt.Println(file.Name())
}

func setAge(age int) error {
	if age < 0 {
		return errors.New("年龄输入不合法")
	}
	fmt.Println(age)
	return nil
}
